﻿using Abp.Threading;
using Quartz;
using Quartz.Impl;

namespace QuartzNetJob
{
    public class QuartzHelper : IQuartzHelper
    {
        // 存储Job的队列 可视化可以用 
        public Dictionary<string, ScheduledTaskBase> QuartzList = new();
        private readonly IScheduler scheduler;
        public QuartzHelper()
        {
            StdSchedulerFactory factory = new();
            scheduler = factory.GetScheduler().Result;
            scheduler.Start().Wait();
        }
        /// <summary>
        ///   添加循环定时任务
        /// </summary>
        /// <typeparam name="T">被执行的类</typeparam>
        /// <param name="Seconds">毫秒</param>
        /// <returns></returns>
        public string SetIntervalJob<T>(int Seconds) where T : ScheduledTaskBase
        {
            // 实例化对象
            ScheduledTaskBase Job = Activator.CreateInstance<T>();
            string JobKey = Guid.NewGuid().ToString();

            IDictionary<string, object> jbData = new Dictionary<string, object>
            {
                { JobKey, Job }
            };
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
             .WithIdentity(JobKey)
             .SetJobData(new JobDataMap(jbData)).Build();
            ITrigger trigger = TriggerBuilder.Create()
             .WithIdentity(JobKey)
             .StartNow()
             .WithSimpleSchedule(x => x.WithIntervalInSeconds(Seconds)
             .RepeatForever())
             .Build();
            QuartzList.Add(JobKey, Job);
            AsyncHelper.RunSync(() => scheduler.ScheduleJob(job1, trigger));
            return JobKey;
        }
        /// <summary>
        ///   添加循环定时任务（带参）
        /// </summary>
        /// <typeparam name="T">被执行的类</typeparam>
        /// <param name="Minutes">分钟</param>
        /// <returns></returns>
        public string SetIntervalJob<T>(int Minutes, object data, string JobKey) where T : ScheduledTaskBase
        {
            // 实例化对象
            ScheduledTaskBase Job = Activator.CreateInstance<T>();

            IDictionary<string, object> jbData = new Dictionary<string, object>
            {
                { JobKey, Job }
            };
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
             .WithIdentity(JobKey)
             .SetJobData(new JobDataMap(jbData)).Build();
            ITrigger trigger = TriggerBuilder.Create()
             .WithIdentity(JobKey)
              .StartAt(DateTimeOffset.Now.AddMinutes(Minutes))
             .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromMinutes(Minutes)).RepeatForever())
             .Build();
            trigger.JobDataMap.Add("Data", data);
            QuartzList.Add(JobKey, Job);
            AsyncHelper.RunSync(() => scheduler.ScheduleJob(job1, trigger));
            return JobKey;
        }
        /// <summary>
        /// 每天定时执行
        /// </summary>
        /// <typeparam name="T">任务类</typeparam>
        /// <param name="h">小时</param>
        /// <param name="m">分钟</param>
        /// <param name="s">秒</param>
        /// <returns>jobKey</returns>
        public string SetDailyJob<T>(int h, int m, int s) where T : ScheduledTaskBase
        {
            ScheduledTaskBase Job = Activator.CreateInstance<T>();
            string JobKey = Guid.NewGuid().ToString();
            IDictionary<string, object> jbData = new Dictionary<string, object>
            {
                { JobKey, Job }
            };
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
            .WithIdentity(JobKey)
            .SetJobData(new JobDataMap(jbData)).Build();
            ITrigger trigger = TriggerBuilder.Create()
               .WithIdentity(JobKey)
               .StartNow()
               .WithCronSchedule($"{s} {m} {h} * * ?")//每天定时
               .Build();
            AsyncHelper.RunSync(() => scheduler.ScheduleJob(job1, trigger));
            QuartzList.Add(JobKey, Job);
            return JobKey;
        }
        /// <summary>
        /// 延迟执行
        /// </summary>
        /// <typeparam name="T">方法类</typeparam>
        /// <param name="delay">延迟时间</param>
        /// <returns></returns>
        public string SetDelayJob<T>(DateTimeOffset delay, bool isFirst) where T : ScheduledTaskBase
        {
            ScheduledTaskBase Job = Activator.CreateInstance<T>();
            string JobKey = Guid.NewGuid().ToString();
            IDictionary<string, object> jbData = new Dictionary<string, object>
            {
                { JobKey, Job }
            };
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
           .WithIdentity(JobKey)
           .SetJobData(new JobDataMap(jbData)).Build();
            ITrigger trigger;
            if (isFirst)
            {
                trigger = TriggerBuilder.Create()
                .WithIdentity(JobKey)
                .StartNow()
                .StartAt(delay)
                .Build();
            }
            else
            {
                trigger = TriggerBuilder.Create()
                .WithIdentity(JobKey)
                .StartAt(delay)
                .Build();
            }
            AsyncHelper.RunSync(() => scheduler.ScheduleJob(job1, trigger));
            QuartzList.Add(JobKey, Job);
            return JobKey;
        }
        /// <summary>
        /// 延迟执行（带参）
        /// </summary>
        /// <typeparam name="T">方法类</typeparam>
        /// <param name="delay">延迟时间</param>
        /// <returns></returns>
        public void SetDelayJob<T>(DateTimeOffset delay, bool isFirst, object data, string JobKey) where T : ScheduledTaskBase
        {
            ScheduledTaskBase Job = Activator.CreateInstance<T>();
            IDictionary<string, object> jbData = new Dictionary<string, object>
            {
                { JobKey, Job }
            };
            IJobDetail job1 = JobBuilder.Create<JobInstance>()
           .WithIdentity(JobKey)
           .SetJobData(new JobDataMap(jbData)).Build();
            ITrigger trigger = TriggerBuilder.Create()
              .WithIdentity(JobKey)
              .StartAt(delay)
              .Build();
            trigger.JobDataMap.Add("Data", data);
            AsyncHelper.RunSync(() => scheduler.ScheduleJob(job1, trigger));
            QuartzList.Add(JobKey, Job);
        }
        /// <summary>
        ///  删除任务
        /// </summary>
        /// <param name="JobKey"></param>
        public bool RemoveJob(string JobKey)
        {
            try
            {
                AsyncHelper.RunSync(() => scheduler.DeleteJob(new JobKey(JobKey)));
                QuartzList.Remove(JobKey);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        ///  暂停所有Job
        /// </summary>
        /// <returns></returns>
        public bool PauseAllJobs()
        {
            try
            {
                scheduler.PauseAll();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 恢复所有任务
        /// </summary>
        /// <returns></returns>
        public bool ResumeAllJobs()
        {
            try
            {
                scheduler.ResumeAll();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 恢复任务
        /// </summary>
        /// <param name="jobId"></param>
        public void ResumeJob(string jobId)
        {

            AsyncHelper.RunSync(() => scheduler.ResumeJob(new JobKey(jobId)));
        }
        /// <summary>
        ///  关闭所有任务,清理资源再也无法开始
        /// </summary>
        /// <returns></returns>
        public bool ShutDownAllJobs()
        {
            try
            {
                if (!scheduler.IsShutdown)
                {
                    scheduler.Shutdown();
                    QuartzList.Clear();
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        ///  启动所有Job
        /// </summary>
        /// <returns></returns>
        public bool StartAllJob()
        {
            try
            {
                scheduler.Start();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        ///  暂停单个Job
        /// </summary>
        /// <param name="JobKey">任务Id</param>
        public bool StopJob(string JobKey)
        {
            try
            {
                AsyncHelper.RunSync(() => scheduler.PauseJob(new JobKey(JobKey)));
                return true;
            }
            catch (Exception)
            {

                return false;
            }
        }
        // 启动Job的 内部类
        private class JobInstance : IJob
        {
            public async Task Execute(IJobExecutionContext context)
            {
                IDictionary<string, object> jobs = context.JobDetail.JobDataMap;
                if (jobs != null)
                {

#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
                    ScheduledTaskBase jobObj = jobs.Values.FirstOrDefault() as ScheduledTaskBase;
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
#pragma warning disable CS8602 // 解引用可能出现空引用。
                    await jobObj.RunAsync(context);
#pragma warning restore CS8602 // 解引用可能出现空引用。
                }
            }
        }

    }


}
